package com.base.service.impl;

import com.base.service.SqlStatementBuilder;
import com.base.dialects.Dialects;
import com.base.query.CustomizeQueryWrapper;
import com.base.vo.Field;
import com.base.vo.Filters;
import org.apache.commons.lang.StringUtils;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wnhuang
 * @Package com.base.api.service.impl
 * @date 2021-03-18 23:59
 */
public class DefaultSqlStatementBuilderImpl implements SqlStatementBuilder {

    private final static Integer DATATYPE_STRING = 1;
    private final static Integer DATATYPE_NUMBER = 2;
    private final static Integer DATATYPE_DATETIME = 4;


    /**
     * 构建SELECT部分
     *
     * @param fieldsList
     * @param dialect
     * @return
     */
    @Override
    public void builderSelect(List<Field> fieldsList, CustomizeQueryWrapper queryWrapper, Dialects dialect) {
        for (Field field : fieldsList) {
            if (StringUtils.isNotBlank(field.getExpression())) {
                if (field.getSlaveType() == 1) {
                    field.setGroup(false);
                }
                continue;
            }
            Integer aggregateMode = field.getAggregateMode();
            String systemName = field.getSystemName();
            Integer dataType = field.getDataType();
            //度量
            if (field.getSlaveType() == 1) {
                field.setGroup(false);
                if (aggregateMode == null) {
                    aggregateMode = 0;
                }
                switch (aggregateMode) {
                    case 0:
                        field.setExpression(systemName);
                        break;
                    case 1: {
                        if (field.getDistinct() != null && field.getDistinct()) {
                            field.setExpression("COUNT(DISTINCT(" + systemName + "))");
                        } else {
                            field.setExpression("COUNT(" + systemName + ")");
                        }
                        break;
                    }
                    case 2:
                        field.setExpression("MAX(" + systemName + ")");
                        break;
                    case 3:
                        field.setExpression("MIN(" + systemName + ")");
                        break;
                    case 4:
                        field.setExpression("SUM(" + systemName + ")");
                        break;
                    case 5:
                        field.setExpression("AVG(" + systemName + ")");
                        break;
                }
            } else {
                //维度
                //日期类型分组
                if (DATATYPE_DATETIME.equals(dataType)) {
                    String dateTimeSub = field.getDateTimeSub();
                    switch (dateTimeSub) {
                        case "year":
                            field.setExpression(dialect.convertDateToString(systemName, "yyyy"));
                            break;
                        case "_ym":
                            field.setExpression(dialect.convertDateToString(systemName, "yyyyMM"));
                            break;
                        case "_ymd":
                            field.setExpression(dialect.convertDateToString(systemName, "yyyyMMdd"));
                            break;
                        case "month":
                            field.setExpression(dialect.convertDateToString(systemName, "MM"));
                            break;
                        case "day":
                            field.setExpression(dialect.convertDateToString(systemName, "dd"));
                            break;
                    }
                } else {
                    field.setExpression(systemName);
                }
            }
        }
        if (!fieldsList.isEmpty()) {
            queryWrapper.select(fieldsList);
        }
    }

    /**
     * 构建WHERE部分
     *
     * @param filtersList
     * @param dialect
     * @return
     */
    @Override
    public void builderWhere(List<Filters> filtersList, CustomizeQueryWrapper queryWrapper, Dialects dialect) {
        if (filtersList == null || filtersList.isEmpty()) {
            return;
        }
        for (Filters filters : filtersList) {
            Field field = filters.getField();
            String systemName = field.getSystemName();
            Integer filterMode = filters.getFilterMode();
            String matchValue = filters.getMatchValue();
            //日期类型
            if (filters.getField().getDataType() == DATATYPE_DATETIME) {
                LocalDate beginDate = null;
                LocalDate endDate = null;
                if (filterMode == 5) {
                    switch (matchValue) {
                        case "today":
                            beginDate = endDate = LocalDate.now();
                            break;
                        case "yesterday":
                            beginDate = endDate = LocalDate.now().minusDays(1);
                            break;
                        case "thisMonth":
                            beginDate = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
                            endDate = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
                            break;
                        case "lastMonth":
                            beginDate = LocalDate.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
                            endDate = LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                            break;
                        case "thisYear":
                            beginDate = LocalDate.now().with(TemporalAdjusters.firstDayOfYear());
                            endDate = LocalDate.now().with(TemporalAdjusters.lastDayOfYear());
                            break;
                        case "lastYear":
                            beginDate = LocalDate.now().minusYears(1).with(TemporalAdjusters.firstDayOfYear());
                            endDate = LocalDate.now().minusYears(1).with(TemporalAdjusters.lastDayOfYear());
                            break;
                    }
                    endDate = endDate.plusDays(1);
                    queryWrapper.ge(systemName, beginDate);
                    queryWrapper.lt(systemName,  endDate);

                }
                if (filterMode == 4) {
                    if (filters.getBeginDate() != null) {
                        beginDate = filters.getBeginDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        queryWrapper.ge(systemName, beginDate);
                    }
                    if (filters.getEndDate() != null) {
                        endDate = filters.getEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().plusDays(1);
                        queryWrapper.lt(systemName, endDate);
                    }
                }
            }

            //数值类型
            if (filters.getField().getDataType() == DATATYPE_NUMBER) {
                if (filters.getMaxValue() != null) {
                    queryWrapper.le(systemName, filters.getMaxValue());
                }
                if (filters.getMinValue() != null) {
                    queryWrapper.ge(systemName, filters.getMinValue());
                }
            }

            //字符类型
            if (filters.getField().getDataType() == DATATYPE_STRING) {
                if (filterMode == 0) {
                    queryWrapper.in(!filters.getFilterItems().isEmpty(), systemName, filters.getFilterItems());
                }
                if (filterMode == 1) {
                    queryWrapper.notIn(!filters.getFilterItems().isEmpty(), systemName, filters.getFilterItems());
                }
                if (filterMode == 2) {
                    queryWrapper.eq(StringUtils.isNotBlank(matchValue), systemName, matchValue);
                }
                if (filterMode == 3) {
                    queryWrapper.like(StringUtils.isNotBlank(matchValue), systemName, matchValue);
                }
            }
        }
    }

    /**
     * 构建GROUPBY部分
     *
     * @param fieldsList
     * @return
     */
    @Override
    public void builderGroup(List<Field> fieldsList, CustomizeQueryWrapper queryWrapper) {
        List<Field> collect = fieldsList.stream().filter(t -> t.getGroup()).collect(Collectors.toList());
        queryWrapper.groupByField(collect);
    }

    /**
     * 构建ORDERBY部分
     *
     * @param fieldsList
     * @return
     */
    @Override
    public void builderOrderBy(List<Field> fieldsList, CustomizeQueryWrapper queryWrapper) {
        List<Field> collect = fieldsList.stream().filter(t -> StringUtils.isNotBlank(t.getSortMode())).collect(Collectors.toList());
        queryWrapper.orderBy(collect);
    }
}
